<template>
	<div class="component-container">
		<!-- 搜索表单 -->
		<el-form ref="queryFormRef" :model="queryParams" :inline="true">
			<el-form-item><el-button type="success" :icon="Plus" @click="handleAdd">新增</el-button></el-form-item>

			<el-form-item prop="name"><el-input v-model="queryParams.name" placeholder="菜单标题" clearable @keyup.enter="handleQuery" /></el-form-item>
			<el-form-item>
				<el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
				<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
			</el-form-item>
		</el-form>

		<!-- 数据表格 -->
		<el-table
			v-loading="loading"
			:data="menuList"
			highlight-current-row
			:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
			@row-click="handleRowClick"
			row-key="name"
			border
		>
			<el-table-column label="菜单标题">
				<template #default="scope">
					<svg-icon color="#333" :icon-class="scope.row.icon ? scope.row.icon : 'build'" />
					{{ scope.row.meta.title }}
				</template>
			</el-table-column>

			<el-table-column label="状态" align="center" width="100">
				<template #default="scope">
					<el-tag v-if="!scope.row.meta.hidden" type="success">显示</el-tag>
					<el-tag v-else type="info">隐藏</el-tag>
				</template>
			</el-table-column>

			<el-table-column label="排序" align="center" width="100" prop="sort"></el-table-column>

			<el-table-column label="操作" align="center" width="200">
				<template #default="scope">
					<!--<el-button type="success" :icon="Plus" circle plain @click.stop="handleAdd(scope.row)" />-->
					<el-button type="primary" :icon="Edit" circle plain @click.stop="handleUpdate(scope.row)" />
					<el-button type="danger" :icon="Delete" circle plain @click.stop="handleDelete(scope.row)" />
				</template>
			</el-table-column>
		</el-table>

		<!-- 弹窗表单 -->
		<el-dialog :title="dialog.title" v-model="dialog.visible" @close="cancel" width="750px">
			<el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
				<el-form-item label="父级菜单" prop="parentId">
					<el-tree-select v-model="formData.parentId" placeholder="选择上级菜单" :data="menuOptions" filterable check-strictly />
					<el-form-item label="角色" prop="role"><el-input v-model="formData.role" placeholder="请输入菜单需要角色,多个用','隔开" /></el-form-item>
				</el-form-item>
				<el-form-item label="菜单标题" prop="title"><el-input v-model="formData.title" placeholder="请输入菜单标题,用于显示" /></el-form-item>
				<el-form-item label="菜单名称" prop="name"><el-input v-model="formData.name" placeholder="请输入菜单名称,用于程序识别" /></el-form-item>

				<el-form-item label="菜单类型" prop="type">
					<el-radio-group v-model="formData.type" @change="handleMenuTypeChange">
						<el-radio label="MENU">菜单</el-radio>
						<el-radio label="CATALOG">目录</el-radio>
						<el-radio label="EXTLINK">外链</el-radio>
					</el-radio-group>
				</el-form-item>

				<!-- 路由路径(浏览器地址栏显示) -->
				<el-form-item v-if="formData.type == 'EXTLINK'" label="外链地址" prop="path"><el-input v-model="formData.path" placeholder="请输入外链完整路径" /></el-form-item>

				<el-form-item v-else label="路由路径" prop="path">
					<el-input v-if="formData.type == 'CATALOG'" v-model="formData.path" placeholder="/system  (注意:目录必须以/开头)" />
					<el-input v-else v-model="formData.path" placeholder="/user (注意:浏览器地址栏显示,必须以/开头表示绝对路径)" />
				</el-form-item>

				<!-- 组件页面完整路径 -->
				<el-form-item v-if="formData.type == 'MENU'" label="组件路径" prop="component">
					<el-input v-model="formData.component" placeholder="system/user/index" style="width: 95%">
						<template v-if="formData.parentId != '0'" #prepend>
							src/views/
						</template>
						<template v-if="formData.parentId != '0'" #append>
							.vue
						</template>
					</el-input>
				</el-form-item>

				<el-form-item label="图标" prop="icon">
					<el-popover ref="popoverRef" placement="bottom-start" :width="570" trigger="click">
						<template #reference>
							<el-input v-model="formData.icon" placeholder="点击选择图标" readonly @click="iconSelectVisible = true">
								<template #prefix>
									<svg-icon :icon-class="formData.icon" />
								</template>
							</el-input>
						</template>

						<icon-select @selected="selected" />
					</el-popover>
				</el-form-item>

				<el-form-item label="跳转路由" prop="redirect"><el-input v-model="formData.redirect" placeholder="redirect跳转到路由路径(/开头)" maxlength="50" /></el-form-item>

				<el-form-item label="状态" prop="visible">
					<el-radio-group v-model="formData.visible">
						<el-radio :label="true">显示</el-radio>
						<el-radio :label="false">隐藏</el-radio>
					</el-radio-group>
				</el-form-item>
				<el-form-item label="总是显示" prop="alwaysShow">
					<el-tooltip
						class="box-item"
						effect="dark"
						content="本菜单是否总是显示,用于一个本菜单只有一个子菜单的时候，本菜单是否显示。true显示本菜单并带有右箭头，false只显示子菜单不带右箭头."
						placement="right"
					>
						<el-radio-group v-model="formData.alwaysShow">
							<el-radio :label="true">是</el-radio>
							<el-radio :label="false">否</el-radio>
						</el-radio-group>
					</el-tooltip>
				</el-form-item>
				<el-form-item label="排序" prop="sort">
					<el-tooltip class="box-item" effect="dark" content="数字越大越靠前" placement="right">
						<el-input-number v-model="formData.sort" style="width: 100px" controls-position="right" :min="0" />
					</el-tooltip>
				</el-form-item>
			</el-form>

			<template #footer>
				<div class="dialog-footer">
					<el-button type="primary" @click="submitForm">确 定</el-button>
					<el-button @click="cancel">取 消</el-button>
				</div>
			</template>
		</el-dialog>
	</div>
</template>

<script setup lang="ts">
import { reactive, ref, onMounted, toRefs,nextTick } from 'vue';

import { Search, Plus, Edit, Refresh, Delete } from '@element-plus/icons-vue';
import { ElForm, ElMessage, ElMessageBox, ElPopover } from 'element-plus';

import { Dialog, Option } from '@/types/common';
//import localAsyncRoutes from '@/router/modules/localAsyncRoutes.json';

import { MenuItem, MenuQueryParam } from '@/codegen/types/menu';
// API 依赖
/* import {
  listMenus,
  getMenuDetail,
  listSelectMenus,
  addMenu,
  deleteMenus,
  updateMenu,
} from '@/api/system/menu';
 */
import { saveMenu, listMenus } from '@/codegen/api/menu';
import SvgIcon from '@/components/SvgIcon/index.vue';
import IconSelect from '@/components/IconSelect/index.vue';

const emit = defineEmits(['menuClick']);
const queryFormRef = ref(ElForm);
const dataFormRef = ref(ElForm);
const popoverRef = ref(ElPopover);
const defaultForm = {
		parentId: '0',//父菜单ID
		title: '',//显示标题
		name: '',//菜单名称用于程序标识，英文
		path: '',//路由路径
		role: 'admin,user,dev',//菜单角色
		sort: 1,//排序
		component: 'Layout',//组件路径
		type: 'MENU',//菜单类型(1:菜单；2：目录；3：外链)
		redirect: '',//redirect: '/nested/level1/level2',  重定向路由  noRedirect
		visible: true,//菜单是否可见(1:是;0:否;)
		alwaysShow: false,//菜单总是否可见(1:是;0:否;)  上级目录是否总是显示，设置一个父菜单只有一个子菜单的时候，父菜单是否显示。true显示父菜单，false只显示子菜单
		icon: ''//图标 
	} as MenuItem
//本地数据
var localAsyncRoutes = ref([] as MenuItem[]);
const state = reactive({
	loading: true,
	// 选中ID数组
	ids: [],
	// 非单个禁用
	single: true,
	// 非多个禁用
	multiple: true,
	queryParams: {} as MenuQueryParam,
	menuList: [] as MenuItem[],
	dialog: { visible: false } as Dialog,
	formData: Object.assign({}, defaultForm) as MenuItem,
	rules: {
		parentId: [{ required: true, message: '请选择顶级菜单', trigger: 'blur' }],
		title: [{ required: true, message: '请输入菜单标题', trigger: 'blur' }],
		name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
		type: [{ required: true, message: '请选择菜单类型', trigger: 'blur' }],
		path: [{ required: true, message: '请输入路由路径', trigger: 'blur' }],
		component: [{ required: true, message: '请输入组件完整路径', trigger: 'blur' }]
	},
	menuOptions: [] as Option[],
	currentRow: undefined,
	// Icon选择器显示状态
	iconSelectVisible: false,
	cacheData: {
		menuType: '',
		menuPath: ''
	}
});

const { loading, queryParams, menuList, dialog, formData, rules, menuOptions, iconSelectVisible, cacheData } = toRefs(state);

//const targetData =[];
function loopsMenu(localmenus = [] as MenuItem[]  ) {
	return localmenus.map(item  => {
		var node = {
			value: item.name,
			label: item.meta.title,
			checked: false,
			children :[] as  any
		};
		//targetData.push(node);
		if (item.children && item.children.length) {
			node.children = loopsMenu(item.children);
		}
		return node;
	});
}
async function listSelectMenus() {
	return new Promise((resolve, reject) => {
		return listMenus().then(({ data }) => {
			//console.log(data.data);
			var d = data.data;
			if (typeof d == 'string') {
				d = JSON.parse(d);
			}
			//console.log(d);
			localAsyncRoutes.value = d;
			//console.log(localAsyncRoutes.value)
			//var data = loopsMenu(localAsyncRoutes);
			resolve(loopsMenu(d));
		});
	});
}
/**
 * 查询
 */
function handleQuery() {
	// 重置父组件
	emit('menuClick', null);
	state.loading = false;
	/*
	listMenus(state.queryParams).then(({ data }) => {
		state.menuList = data;
		state.loading = false;
	});
	*/
	listSelectMenus().then(data => {
		//state.menuList = data;
		state.menuList = localAsyncRoutes.value;
		//console.log(localAsyncRoutes);
		state.loading = false;
	});
}

/**
 * 加载菜单下拉树
 */
async function loadMenuData() {
	const menuOptions: any[] = [];
	await listSelectMenus().then(data => {
		const menuOption = { value: '0', label: '顶级菜单', children: data };
		menuOptions.push(menuOption);
		state.menuOptions = menuOptions;
	});
}

/**
 * 重置查询
 */
function resetQuery() {
	queryFormRef.value.resetFields();
	handleQuery();
}
/**
 * 重置表单数据默认值
 */
function resetForm() {
	state.formData=Object.assign({}, defaultForm)
}
function handleRowClick(row: any) {
	state.currentRow = JSON.parse(JSON.stringify(row));
	emit('menuClick', row);
}
async function handleAdd(row: any) {
	state.formData.id = undefined;
	await loadMenuData();
	state.dialog = {
		title: '添加菜单',
		visible: true
	};
	if (row.id) {
		// 行点击新增
		state.formData.parentId = row.id;
		if (row.id == '0') {
			state.formData.type = 'CATALOG';
		} else {
			state.formData.type = 'MENU';
		}
	} else {
		// 工具栏新增
		if (state.currentRow) {
			state.formData.parentId = (state.currentRow as any).id;
			state.formData.type = 'MENU';
		} else {
			state.formData.parentId = '0';
			state.formData.type = 'CATALOG';
		}
	}
}
function loopSelectMenu(name :string, localmenus = [] as MenuItem[], parent?:MenuItem) {
	let ret = null as any;
	for (let item of localmenus) {
		if (item.name == name) {
			item.parentId = parent ? parent.name : '0';
			ret = item;
			break;
		} else if (item.children && item.children.length) {
			ret = loopSelectMenu(name, item.children, item);
			if (ret) break;
		}
	}
	return ret;
}

/**
 * 修改弹窗
 */
async function handleUpdate(row: any) {
	await loadMenuData();
	state.dialog = {
		title: '修改菜单',
		visible: true
	};
	const name = row.name;
	var m = loopSelectMenu(name, localAsyncRoutes.value,undefined);
	//console.log(localAsyncRoutes.value)
	state.formData = {
		id: m.name,
		parentId: m.parentId,
		title: m.meta.title,
		name: m.name,
		path: m.path,
		visible: !m.meta.hidden,
		role: m.meta.roles?.join(","),
		sort: m.meta.sort,
		component: m.component,
		type: m.meta.type || 'MENU',
		redirect: m.redirect,
		alwaysShow: m.meta.alwaysShow,
		icon: m.meta.icon
	};
	cacheData.value.menuType = state.formData.type;
	cacheData.value.menuPath = state.formData.path;
	/*
  getMenuDetail(id).then(({ data }) => {
    state.formData = data;
    cacheData.value.menuType = data.type;
    cacheData.value.menuPath = data.path;
  });*/
}

/**
 * 菜单类型change事件
 */
function handleMenuTypeChange(val: any) {
	if (val !== cacheData.value.menuType) {
		formData.value.path = '';
		// console.log(state.formData.parentId)
		if(!state.formData.id&&state.formData.parentId!='0'){
			state.formData.component=""
		}else{
			state.formData.component="Layout"
		}
	} else {
		formData.value.path = cacheData.value.menuPath;
	}
}

function loopSelectParentMenu(parentId:string, localmenus = []as MenuItem[]) {
	let ret = null as any;
	for (let item of localmenus) {
		//console.log(item.name+"--"+parentId)
		if (item.name == parentId) {
			ret = item;
			break;
		} else if (item.children && item.children.length) {
			ret = loopSelectParentMenu(parentId, item.children);
			if (ret) break;
		}
	}
	return ret;
}
function loopSortMenu(localmenus = []as MenuItem[]) {
	localmenus.sort((x, y) => {
		var xsort = x.meta.sort ? x.meta.sort : 0;
		var ysort = y.meta.sort ? y.meta.sort : 0;
		//console.log(xsort-ysort )
		return ysort - xsort;
	}); // 正序

	for (let item of localmenus) {
		//console.log(item.name+"--"+parentId)
		if (item.children && item.children.length) {
			loopSortMenu(item.children);
		}
	}
}
/**
 * 菜单提交
 */
async  function submitForm() {
	await dataFormRef.value?.validate((valid: boolean, fields :any) => {
	    if (valid) {
	      var menu = {
	      	path: state.formData.path,
	      	component: state.formData.component,
	      	redirect: state.formData.redirect,
	      	name: state.formData.name,
	      	meta: {
	      		roles: state.formData.role.split(','),
	      		title: state.formData.title,
	      		icon: state.formData.icon,
	      		hidden: !state.formData.visible,
	      		alwaysShow: state.formData.alwaysShow,
	      		sort: state.formData.sort,
	      		type: state.formData.type
	      	}
	      } as  MenuItem;
          if(!state.formData.id){//增加
			  if (state.formData.parentId == '0') {//顶级目录
				localAsyncRoutes.value.push(menu);
				var m = localAsyncRoutes.value;
				loopSortMenu(m);
				//console.log(menu )
				saveMenu(m);
				//console.log(localAsyncRoutes);
			  } else {
				var p = loopSelectParentMenu(state.formData.parentId, localAsyncRoutes.value);
				if (!p.children) {
					p.children = [];
				}
				p.children.push(menu);
				var m = localAsyncRoutes.value;
				loopSortMenu(m);
				//console.log(menu )
				saveMenu(m);
			  }

		   }else{//修改
              var mm = loopSelectMenu(state.formData.id, localAsyncRoutes.value,undefined) ;
			  //console.log(m);
			  if(mm){
				  Object.assign(mm, menu)
				  var m = localAsyncRoutes.value;
				  saveMenu(m);
			  }
		   }
	    } else {
	      console.error('error submit!', fields)
	    }
	})
}
// 从一个多维数据组删除一个指定key的值
const loopDeleteMenu = (localmenus=[] as MenuItem[], name:string) => {
    localmenus.forEach((item, index) => {
        if (item.name ===name) {
            localmenus.splice(index, 1)
        }
        if (item.children &&  item.children.length > 0) {
            return loopDeleteMenu(item.children, name)
        }
    })
}
function handleDelete(row: any) {
	// const ids = [row.id || state.ids].join(',');
	var name = row.name;
	ElMessageBox.confirm('确认删除已选中的数据项?', '警告', {
		confirmButtonText: '确定',
		cancelButtonText: '取消',
		type: 'warning'
	})
		.then(() => {
			loopDeleteMenu(localAsyncRoutes.value, name);
			//console.log(localAsyncRoutes.value)
			saveMenu(localAsyncRoutes.value);
			/*
      deleteMenus(ids).then(() => {
        ElMessage.success('删除成功');
        handleQuery();
      });*/
		})
		.catch(() => ElMessage.info('已取消删除'));
}
/**
 * 取消关闭弹窗
 */
function cancel() {
	dataFormRef.value?.resetFields()
	state.dialog.visible = false;
	resetForm();//重置表单
	nextTick(() => {
	  dataFormRef.value?.clearValidate();
	});
}
/**
 * 选择图标后事件
 */
function selected(name: string) {
	state.formData.icon = name;
	state.iconSelectVisible = false;
}

onMounted(() => {
	handleQuery();
});
</script>
